package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;

import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 赵博凯
 * @since 2025-10-25
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final InteractionQuestionServiceImpl questionService;
    private final RemarkClient remarkClient;
    private final UserClient userClient;


    @Override
    @Transactional
    public void saveReply(ReplyDTO replyDTO) {
        // 1. 获取当前登录用户
        Long userId = UserContext.getUser();

        // 2. 创建回复实体
        InteractionReply interactionReply = BeanUtils.copyProperties(replyDTO, InteractionReply.class);
        interactionReply.setUserId(userId);
       /* InteractionReply reply = new InteractionReply();
        reply.setUserId(userId);
        reply.setContent(replyDTO.getContent());
        reply.setAnonymity(replyDTO.getAnonymity());
        reply.setQuestionId(replyDTO.getQuestionId());
        reply.setAnswerId(replyDTO.getAnswerId());
        reply.setTargetReplyId(replyDTO.getTargetReplyId());
        reply.setTargetUserId(replyDTO.getTargetUserId());
        reply.setReplyTimes(replyDTO.getReplyTimes());*/

        // 先保存回复，以便获取ID
        save(interactionReply);

        // 4. 如果是回答（answerId为空），更新问题的latestAnswerId
        if (replyDTO.getAnswerId() == null) {
            LambdaUpdateWrapper<InteractionQuestion> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId, interactionReply.getId());
            questionService.update(updateWrapper);
        }
        // 5. 如果是评论和回复，更新回答里的评论次数
        if (replyDTO.getAnswerId() != null) {
            LambdaUpdateWrapper<InteractionReply> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .set(InteractionReply::getReplyTimes, (interactionReply.getReplyTimes() == null ? 0 : interactionReply.getReplyTimes()) + 1);
            update(updateWrapper);
        }
        // 6. 如果是学生提交，更新问题状态为未查看
        if (replyDTO.getIsStudent()) {
            LambdaUpdateWrapper<InteractionQuestion> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .set(InteractionQuestion::getStatus, QuestionStatus.UN_CHECK);
            questionService.update(updateWrapper);
        }

        // 7. 更新问题的回答次数（使用原子操作）
        questionService.lambdaUpdate()
                .eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                .setSql("answer_times = answer_times + 1")
                .update();

    }


    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery pageQuery, boolean isStudent) {
      /*  // 1. 构建查询条件
        Page<InteractionReply> page = lambdaQuery()
                //.eq(pageQuery.getQuestionId() != null, InteractionReply::getQuestionId, pageQuery.getQuestionId())
                .eq(pageQuery.getAnswerId() == null, InteractionReply::getQuestionId, pageQuery.getQuestionId())
                // 当answerId为空时，查询问题下的一级评论
                .eq(pageQuery.getAnswerId() != null, InteractionReply::getAnswerId, pageQuery.getAnswerId())
                .eq(InteractionReply::getHidden, false) // 只查询未隐藏的回复
                .orderByAsc(InteractionReply::getCreateTime)
                .page(new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize()));*/
        Long questionId = pageQuery.getQuestionId();
        Long answerId = pageQuery.getAnswerId();

        Boolean isAnswer = questionId != null;
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(isAnswer, InteractionReply::getQuestionId, questionId)
                .eq(isStudent, InteractionReply::getHidden, false)
                .eq(InteractionReply::getAnswerId, isAnswer ? 0L : answerId)
                .eq(InteractionReply::getHidden, false)
                .page(pageQuery.toMpPage(//根据点赞数排序再根据创建时间排序
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)));

        // 4. 查询用户对这些回复的点赞状态
        // 先收集回复ID到List中
        List<Long> replyIds = page.getRecords().stream()
                .map(InteractionReply::getId)
                .collect(Collectors.toList());
        // 调用远程服务查询点赞状态
        Set<Long> liked = remarkClient.isBizLiked(replyIds);


        // 2. 数据转换
        if (CollUtils.isEmpty(page.getRecords())) {
            return PageDTO.empty(page);
        }

        // 3. 批量查询用户信息
        Set<Long> userIds = page.getRecords().stream()
                .map(InteractionReply::getUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 添加目标用户ID到集合中（用于评论场景）
        page.getRecords().stream()
                .map(InteractionReply::getTargetUserId)
                .filter(Objects::nonNull)
                .forEach(userIds::add);

        Map<Long, UserDTO> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap.putAll(userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u)));
        }

        // 4. 转换VO对象

        List<ReplyVO> voList = page.getRecords().stream().map(reply -> {
            ReplyVO vo = BeanUtils.copyProperties(reply, ReplyVO.class);
            vo.setLiked(liked.contains(reply.getId()));


            // 设置回复者信息
            UserDTO replyUser = userMap.get(reply.getUserId());
            if (replyUser != null && !reply.getAnonymity()) {
                vo.setUserId(replyUser.getId());
                vo.setUserName(replyUser.getName());
                vo.setUserIcon(replyUser.getIcon());
                vo.setUserType(replyUser.getType());
            }

            // 如果是评论且有目标用户，则设置目标用户名
            if (reply.getAnswerId() != null && reply.getTargetUserId() != null) {
                UserDTO targetUser = userMap.get(reply.getTargetUserId());
                if (targetUser != null) {
                    vo.setTargetUserName(targetUser.getName());
                }
            }

            // 统计每个评论的回复数量
            if (reply.getAnswerId() != null && reply.getTargetReplyId() == null) {
                // 这是一级评论，需要统计回复数量
                int replyCount = lambdaQuery()
                        .eq(InteractionReply::getTargetReplyId, reply.getId())
                        .count();
                vo.setReplyTimes(replyCount);
            }

            return vo;
        }).collect(Collectors.toList());

        return PageDTO.of(page, voList);
    }

    @Override
    public PageDTO<ReplyVO> queryReply(ReplyPageQuery query, boolean isStudent) {
        // 1. 构建查询条件
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();

        Boolean isAnswer = questionId != null;
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(isAnswer, InteractionReply::getQuestionId, questionId)
                .eq(isStudent, InteractionReply::getHidden, false)

                .eq(InteractionReply::getAnswerId, isAnswer ? 0L : answerId)
                .page(query.toMpPage(//根据点赞数排序再根据创建时间排序
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)));

        // 2. 数据转换
        if (CollUtils.isEmpty(page.getRecords())) {
            return PageDTO.empty(page);
        }

        // 3. 批量查询用户信息
        Set<Long> userIds = page.getRecords().stream()
                .map(InteractionReply::getUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 添加目标用户ID到集合中（用于评论场景）
        page.getRecords().stream()
                .map(InteractionReply::getTargetUserId)
                .filter(Objects::nonNull)
                .forEach(userIds::add);

        Map<Long, UserDTO> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap.putAll(userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u)));
        }

        // 4. 转换VO对象
        List<ReplyVO> voList = page.getRecords().stream().map(reply -> {
            ReplyVO vo = BeanUtils.copyProperties(reply, ReplyVO.class);
            // 设置回复者信息 (管理端无视匿名设置，所有评论都要返回用户信息)
            UserDTO replyUser = userMap.get(reply.getUserId());
            if (replyUser != null) {
                vo.setUserId(replyUser.getId());
                vo.setUserName(replyUser.getName());
                vo.setUserIcon(replyUser.getIcon());
                vo.setUserType(replyUser.getType());
            }

            // 如果是评论且有目标用户，则设置目标用户名
            if (reply.getAnswerId() != null && reply.getTargetUserId() != null) {
                UserDTO targetUser = userMap.get(reply.getTargetUserId());
                if (targetUser != null) {
                    vo.setTargetUserName(targetUser.getName());
                }
            }

            // 统计每个评论的回复数量 (管理端在统计评论数量的时候，被隐藏的评论也要统计)
            if (reply.getAnswerId() != null && reply.getTargetReplyId() == null) {
                // 这是一级评论，需要统计回复数量（包括隐藏的评论）
                int replyCount = lambdaQuery()
                        .eq(InteractionReply::getTargetReplyId, reply.getId())
                        .count();
                vo.setReplyTimes(replyCount);
            }

            return vo;
        }).collect(Collectors.toList());

        return PageDTO.of(page, voList);
    }

    @Override
    @Transactional
    public void hiddenReply(Long id, Boolean hidden) {
        // 1. 先更新当前回答或评论的隐藏状态
        lambdaUpdate()
                .eq(InteractionReply::getId, id)
                .set(InteractionReply::getHidden, hidden)
                .update();

        // 2. 查询该记录是否为回答（answerId为0表示是一级回答）
        InteractionReply reply = getById(id);
        if (reply != null && reply.getAnswerId() == 0) {
            // 3. 如果是回答，则同时隐藏/显示该回答下的所有评论
            lambdaUpdate()
                    .eq(InteractionReply::getAnswerId, id)
                    .set(InteractionReply::getHidden, hidden)
                    .update();
        }
    }

}